﻿using Microsoft.Extensions.Logging;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZhongJia.Core.Extensions;
using ZhongJia.Core.Tcp;
using ZhongJia.Lock.Core.Dto;
using ZhongJia.Lock.Core.Models;

namespace ZhongJia.Lock.Core.Services
{
    public class TcpService : TcpServerBase<TcpPackage>, ITcpService
    {
        private readonly ILogger _logger;
        public ConcurrentDictionary<SocketAsync<TcpPackage>, string> OnLineDevices { get; set; } = new ConcurrentDictionary<SocketAsync<TcpPackage>, string>();

        public TcpService(
            ILoggerFactory loggerFactory)
        {
            _logger = loggerFactory.CreateLogger<TcpService>();
        }

        public OpenLockResult Open(string deviceSerialNumber)
        {
            var result = new OpenLockResult();
            var client = OnLineDevices.FirstOrDefault(o => o.Value == deviceSerialNumber).Key;
            if (client != null)
            {
                var package = TcpPackage.BuildPacket(6, TcpCommand.Open, deviceSerialNumber);
                client.Send(package);
                _logger.LogInformation($"向锁设备{client.ToString()}发送信息包{package.ToString()}");
                result.IsSuccessed = true;
            }
            else
            {
                result.Error = OpenLockError.LockNotOnlline;
            }
            return result;
        }

        protected override void OnDisconnect(SocketAsync<TcpPackage> client)
        {
            _logger.LogInformation($"有主机断开了连接,当前主机链接数{AliveClients.Count}");
        }

        protected override void OnRecvComplete(SocketAsync<TcpPackage> client, TcpPackage package)
        {
            _logger.LogInformation($"收到基站{client.ToString()}信息包{package.ToString()}");
            switch (package.Command)
            {
                case TcpCommand.Register:
                    var serialNumber = package.GetLockSerialNumber();
                    OnLineDevices.RemoveWhere(o => o.Value == serialNumber);
                    OnLineDevices.AddOrUpdate(client, serialNumber, (t, d) =>
                                    {
                                        d = serialNumber;
                                        return d;
                                    });
                    var sendPackage = TcpPackage.BuildPacket(2, TcpCommand.ResponseRegister);
                    client.Send(sendPackage);
                    break;
            }
        }

        protected override TcpPackage OnReceive(SocketAsync<TcpPackage> client, ByteBuilder recvBuilder)
        {
            return TcpPackage.GetPacket(recvBuilder);
        }

        public void Start(int port)
        {
            StartListen(port);
        }
    }
}
